home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvitops
/
aftopl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-25
|
12KB
|
517 lines
static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/aftopl.c,v 1.4 89/10/02 10:39:25 jjc Rel $";
#include "util.h"
#define MAXNAMES 500
#define NOT_DEFINED 100000.0
#ifndef PI
#define PI 3.14159265358979324
#endif
struct ligatures {
char *ch;
char *succ;
char *lig;
};
char *program_name = "aftopl";
static int lineno = 0;
FILE *infp;
FILE *outfp;
#ifdef PROTO
int lookup(const char *);
char *getkeyvalue(char *, int);
void scan_char_metric(char *);
void compute_font_dimens(void);
void do_kern_pairs(int);
void do_char_metrics(int);
void do_afms(void);
void print_font_dimens(void);
void do_encoding(char *);
void print_char_metrics(void);
void print_lig_kerns(void);
void do_ligatures(struct ligatures *);
#endif
#define bad_afm_file() message(FATAL_ERROR, "bad afm file, line %d", lineno)
struct lig_kern_list {
struct lig_kern_list *next;
int succ;
int lig; /* -1 if its a kern */
double x;
};
struct {
struct lig_kern_list *p;
char *name;
int code;
double llx;
double lly;
double urx;
double ury;
double wx;
} table[MAXNAMES];
struct {
int is_fixed_pitch;
double italic_angle;
double x_height;
/* we use max(urx - wx + italic_correction_space, 0)
as the italic correction for each character */
double italic_correction_space;
double normal_space;
double normal_stretch;
double normal_shrink;
double extra_space;
double quad;
double slant;
} font = { 0, 0.0, NOT_DEFINED, NOT_DEFINED, NOT_DEFINED, NOT_DEFINED,
NOT_DEFINED, NOT_DEFINED, NOT_DEFINED, NOT_DEFINED};
int lookup(s)
const char *s;
{
int i;
for (i = 0; i < MAXNAMES; i++)
if (table[i].name == NULL)
break;
else if (strcmp(table[i].name, s) == 0)
return i;
if (i == MAXNAMES)
message(FATAL_ERROR, "too many names");
if ((table[i].name = malloc(strlen(s) + 1)) == NULL)
message(FATAL_ERROR, "out of memory");
strcpy(table[i].name, s);
table[i].code = -2;
table[i].llx = table[i].lly = 0.0;
table[i].urx = table[i].ury = 0.0;
table[i].wx = 0.0;
table[i].p = NULL;
return i;
}
char *getkeyvalue(s, c)
char *s;
char c;
{
while (*s != '\0') {
while (isspace(*s))
s++;
if (*s == c)
return s + 1;
while (*s != '\0')
if (*s++ == ';')
break;
}
return NULL;
}
void scan_char_metric(s)
char *s;
{
char name[128];
int code, n;
double llx, lly, urx, ury;
double wx, wy;
char *p;
while (isspace(*s))
s++;
if (*s == '\0') /* ignore blank line */
return;
p = getkeyvalue(s, 'N');
if (p == NULL)
bad_afm_file();
/* sscanf(p, " %[A-Za-z0-9]", name); */
/* Microsoft C scanf doesn't understand %[ */
sscanf(p, "%s", name);
if ((p = strchr(name, ';')) != NULL)
*p = '\0';
if ((p = getkeyvalue(s, 'C')) == NULL)
bad_afm_file();
if (sscanf(p, "%d", &code) != 1)
bad_afm_file();
p = getkeyvalue(s, 'B');
if (p == NULL)
bad_afm_file();
if (sscanf(p, "%lg %lg %lg %lg", &llx, &lly, &urx, &ury) != 4)
bad_afm_file();
p = getkeyvalue(s, 'W');
if (p == NULL)
bad_afm_file();
if (*p == 'X') {
if (sscanf(p+1, "%lg", &wx) != 1)
bad_afm_file();
wy = 0.0;
}
else if (sscanf(p, "%lg %lg", &wx, &wy) != 2)
bad_afm_file();
n = lookup(name);
table[n].code = code;
table[n].wx = wx;
table[n].llx = llx;
table[n].lly = lly;
table[n].urx = urx;
table[n].ury = ury;
while ((p = getkeyvalue(s, 'L')) != NULL) {
char successor[128];
char ligature[128];
struct lig_kern_list *ptr;
if (sscanf(p, " %s %s", successor, ligature) != 2)
bad_afm_file();
else if ((s = strchr(ligature, ';')) != NULL)
*s = '\0';
if ((s = strchr(p, ';')) == NULL)
bad_afm_file();
s++;
if ((ptr = (struct lig_kern_list *)malloc(sizeof(struct lig_kern_list))) == NULL)
message(FATAL_ERROR, "out of memory");
ptr->succ = lookup(successor);
ptr->lig = lookup(ligature);
ptr->next = table[n].p;
table[n].p = ptr;
}
}
void compute_font_dimens()
{
if (font.normal_space == NOT_DEFINED) {
int n = lookup("space");
if (table[n].code == -2)
message(FATAL_ERROR, "no char metric for space character");
else
font.normal_space = table[n].wx;
}
if (font.quad == NOT_DEFINED)
font.quad = (font.is_fixed_pitch?2.0:3.0)*font.normal_space;
if (font.italic_correction_space == NOT_DEFINED)
font.italic_correction_space = font.normal_space/12.0;
if (font.normal_shrink == NOT_DEFINED)
font.normal_shrink = font.is_fixed_pitch ? 0.0 :
font.normal_space/3.0;
if (font.normal_stretch == NOT_DEFINED)
font.normal_stretch = font.is_fixed_pitch ? 0.0 :
font.normal_space/2.0;
if (font.extra_space == NOT_DEFINED)
font.extra_space = (font.is_fixed_pitch ? 1.0 :0.5)
*font.normal_space;
if (font.slant == NOT_DEFINED)
if (font.italic_angle == 0.0)
font.slant = 0.0;
else
font.slant = sin(-font.italic_angle*PI/180.0);
if (font.x_height == NOT_DEFINED)
font.x_height = table[lookup("x")].ury;
}
void do_kern_pairs(n)
int n;
{
char buf[512];
char name1[128];
char name2[128];
double x, y;
for (;;) {
int i;
struct lig_kern_list *ptr;
lineno++;
if (fgets(buf, 512, infp) == NULL)
bad_afm_file();
if (buf[0] == '\n')
continue;
if (strcmp(buf, "EndKernPairs\n") == 0)
break;
if (sscanf(buf, "KPX %s %s %lg", name1, name2, &x) != 3) {
if (sscanf(buf, "KP %s %s %lg %lg", name1, name2,
&x, &y) != 4)
bad_afm_file();
}
else
y = 0.0;
i = lookup(name1);
if ((ptr = (struct lig_kern_list *)malloc(sizeof(struct lig_kern_list))) == NULL)
message(FATAL_ERROR, "out of memory");
ptr->succ = lookup(name2);
ptr->lig = -1;
ptr->x = x;
ptr->next = table[i].p;
table[i].p = ptr;
n--;
}
if (n != 0)
message(WARNING, "wrong number of kern pairs");
}
void do_char_metrics(n)
int n;
{
char buf[512];
for (;;) {
char *ptr = buf;
lineno++;
if (fgets(buf, 512, infp) == NULL)
bad_afm_file();
if (strcmp(buf, "EndCharMetrics\n") == 0)
break;
while (isspace(*ptr))
ptr++;
if (*ptr == '\0')
continue;
scan_char_metric(buf);
n--;
}
if (n != 0)
message(WARNING, "wrong number of char metrics");
}
void do_afms()
{
char buf[512];
lineno = 0;
while (fgets(buf, 512, infp) != NULL) {
char *key, *value;
key = buf;
lineno++;
while (isspace(*key))
key++;
value = key;
while (*value != '\0' && !isspace(*value))
value++;
if (*value != '\0') {
/* strip trailing white space */
char *p;
*value++ = '\0';
while (isspace(*value))
value++;
p = value;
while (*p != '\0')
p++;
while (p > value && isspace(*(p-1)))
p--;
*p = '\0';
}
if (strcmp(key, "IsFixedPitch") == 0)
font.is_fixed_pitch = (strcmp(value, "true") == 0);
else if (strcmp(key, "XHeight") == 0)
font.x_height = atof(value);
else if (strcmp(key, "StartCharMetrics") == 0)
do_char_metrics(atoi(value));
else if (strcmp(key, "ItalicAngle") == 0)
font.italic_angle = atof(value);
else if (strcmp(key, "StartKernPairs") == 0)
do_kern_pairs(atoi(value));
else if (strcmp(key, "italicCorrectionSpace") == 0)
font.italic_correction_space = atof(value);
}
}
void print_font_dimens()
{
fprintf(outfp, "(FONTDIMEN\n");
fprintf(outfp, " (SLANT R %f)\n", font.slant);
fprintf(outfp, " (SPACE R %f)\n", font.normal_space/1000.0);
fprintf(outfp, " (SHRINK R %f)\n", font.normal_shrink/1000.0);
fprintf(outfp, " (STRETCH R %f)\n", font.normal_stretch/1000.0);
fprintf(outfp, " (EXTRASPACE R %f)\n", font.extra_space/1000.0);
fprintf(outfp, " (QUAD R %f)\n", font.quad/1000.0);
fprintf(outfp, " (XHEIGHT R %f)\n", font.x_height/1000.0);
fprintf(outfp, " )\n");
}
void do_encoding(encoding)
char *encoding;
{
int i;
char name[256];
FILE *fp;
char *texfonts;
fprintf(outfp, "(CODINGSCHEME %s)\n", encoding);
texfonts = getenv("TEXFONTS");
if (texfonts == NULL)
texfonts = TEXFONTS;
if ((fp = xfopen(encoding, FALSE, texfonts, ".enc")) == NULL)
message(FATAL_ERROR, "can't find %s", encoding);
for (i = 0; i < MAXNAMES; i++)
if (table[i].code >= -1)
table[i].code = -1;
for (i = 0; i < 256 && fscanf(fp, " %s ", name) == 1; i++) {
int n;
if (strcmp(".notdef", name) == 0)
continue;
n = lookup(name);
if (table[n].code == -2)
message(WARNING, "%s in encoding but not in font", name);
else if (table[n].code == -1)
table[n].code = i;
else
message(ERROR, "%s appears more than once in encoding", name);
}
}
void print_char_metrics()
{
int i;
for (i = 0; i < MAXNAMES; i++)
if (table[i].name != NULL && table[i].code > 0) {
double charic;
fprintf(outfp, "(CHARACTER O %03o\n", table[i].code);
fprintf(outfp, " (COMMENT %s)\n", table[i].name);
fprintf(outfp, " (CHARWD R %f)\n",
table[i].wx/1000.0);
/* negative heights and depths mess up \mathaccent */
if (table[i].ury > 0.0)
fprintf(outfp, " (CHARHT R %f)\n",
table[i].ury/1000.0);
if (table[i].lly < 0.0)
fprintf(outfp, " (CHARDP R %f)\n",
-table[i].lly/1000.0);
charic = table[i].urx - table[i].wx + font.italic_correction_space;
if (charic > 0.0)
fprintf(outfp, " (CHARIC R %f)\n",
charic/1000.0);
fputs(" )\n", outfp);
}
}
void print_lig_kerns()
{
int i;
fputs("(LIGTABLE\n", outfp);
for (i = 0; i < MAXNAMES; i++) {
struct lig_kern_list *p;
char label_line[128];
if (table[i].name == NULL || table[i].code < 0)
continue;
sprintf(label_line, " (LABEL O %03o)\n", table[i].code);
/* print the ligatures */
for (p = table[i].p; p != NULL; p = p->next)
if (p->lig != -1 && table[p->lig].code > 0
&& table[p->succ].code > 0) {
fputs(label_line, outfp);
label_line[0]= '\0';
fprintf(outfp," (LIG O %03o O %03o)\n",
table[p->succ].code,
table[p->lig].code);
}
for (p = table[i].p; p != NULL; p = p->next)
if (p->lig == -1 && table[p->succ].code > 0) {
fputs(label_line, outfp);
label_line[0] = '\0';
fprintf(outfp, " (KRN O %03o R %f)\n",
table[p->succ].code,
p->x/1000.0);
}
if (label_line[0] == '\0')
fputs(" (STOP)\n", outfp);
}
fputs(" )\n", outfp);
}
struct ligatures standard_ligatures[] = {
"hyphen", "hyphen", "endash",
"endash", "hyphen", "emdash",
"quoteleft", "quoteleft", "quotedblleft",
"quoteright", "quoteright", "quotedblright",
"exclam", "quoteleft", "exclamdown",
"question", "quoteleft", "questiondown",
NULL, NULL, NULL
};
struct ligatures tt_ligatures[] = {
"exclam", "quoteleft", "exclamdown",
"question", "quoteleft", "questiondown",
NULL, NULL, NULL
};
void do_ligatures(lig)
struct ligatures *lig;
{
int i;
for (i = 0; lig[i].lig != NULL; i++) {
int n;
struct lig_kern_list *p;
n = lookup(lig[i].ch);
if ((p = (struct lig_kern_list *)malloc(sizeof(struct lig_kern_list))) == NULL)
message(FATAL_ERROR, "out_of_memory");
p->succ = lookup(lig[i].succ);
p->lig = lookup(lig[i].lig);
p->next = table[n].p;
table[n].p = p;
}
}
int main(argc, argv)
int argc;
char **argv;
{
char filename[128];
int c;
char *efile = NULL;
int nolig = FALSE;
while ((c = getopt(argc, argv, "ne:")) != EOF)
switch(c) {
case 'n':
nolig = TRUE;
break;
case 'e':
efile = optarg;
break;
case '?':
goto usage;
}
if (argc - optind < 1)
goto usage;
strcpy(filename, argv[optind]);
if (strchr(filename, '.') == NULL)
strcat(filename, ".afm");
if ((infp = fopen(filename, "r")) == NULL)
message(FATAL_ERROR, "can't open %s", filename);
if (argc - optind == 1)
strcpy(strchr(filename, '.'), ".pl");
else if (argc - optind == 2) {
strcpy(filename, argv[optind+1]);
if (strchr(filename, '.') == NULL)
strcat(filename, ".pl");
}
else
goto usage;
if ((outfp = fopen(filename, "w")) == NULL)
message(FATAL_ERROR, "can't open %s", filename);
do_afms();
if (efile != NULL)
do_encoding(efile);
if (!nolig) {
if (font.is_fixed_pitch)
do_ligatures(tt_ligatures);
else
do_ligatures(standard_ligatures);
}
compute_font_dimens();
print_font_dimens();
print_char_metrics();
print_lig_kerns();
exit(history);
usage:
message(FATAL_ERROR, "usage: aftopl [-e encoding] afmfile [plfile]");
}